<?php
  class Template{
    private $template = "";
    private $loop_templates = array();
    private $template_path = "";
    private $loops = array();
    private $ifs = array();
  
    private function read_file($filename){
      $code = "";
      if(file_exists($filename)){
        $templatefile = fopen($filename, "r");
        while(!feof($templatefile)){
          $code = $code.fgets($templatefile, 1024);
        }
        fclose($templatefile);
      }
      return $code;
    }
  
    private function initialize_loops($template){
      preg_match_all("/[^\\\\]{LOOP:([\w]+)[^}]*}((\s*?.*?)*){\/LOOP:\\1}/", $template, $matches, PREG_SET_ORDER);
      
      foreach ($matches as $match) {
        $template = str_ireplace($match[0], "<!--LOOP(".$match[1].")-->", $template);
        $this->loop_templates[strtoupper($match[1])] = $match[2];
        if(!array_key_exists(strtoupper($match[1]), $this->loops)){
          $this->loops[strtoupper($match[1])] = array();
        }
      }
        
      return $template;
  }
  
    public function load($template){
      $path = $this->getTemplatePath($template);
      if(file_exists($path)){
        $template = $this->read_file($path);
      }
      elseif(file_exists($this->template_path."/".$template)){
        $template = $this->read_file($template_path."/".$template);
      }
      $template = $this->initialize_loops($template);
      $this->template = $template;
    }
    
    public function getTemplatePath($name){
      $namespaces = explode("_",strtolower($name));
      $res = Settings::getInstance()->get("root");
      $skin = SkinController::getCurrentSkinName();
      $imported = false;
      if(sizeOf($namespaces) == 3){
        if($namespaces[0] == "plugin"){
          if(file_exists(Settings::getInstance()->get("root")."/system/skins/".$skin."/templates/plugins/".$namespaces[1]."/".$namespaces[2].".html")){
            $res .= "/system/skins/".$skin."/templates/plugins/".$namespaces[1]."/".$namespaces[2].".html";
          }
          else{
            $res .= "/system/plugins/".$namespaces[1]."/templates/".$namespaces[2].".html";
          }
          $imported = true;
        }
      }
      else if(sizeOf($namespaces) == 2){
        if($namespaces[0] == "form"){
          if(file_exists(Settings::getInstance()->get("root")."/system/skins/".$skin."/templates/forms/".$namespaces[1].".html")){
            $res .= "/system/skins/".$skin."/templates/forms/".$namespaces[1].".html";
          }
          else{
            $res .= "/system/templates/forms/".$namespaces[1].".html";
          }
          $imported = true;
        }
        else if($namespaces[0] == "control"){
          if(file_exists(Settings::getInstance()->get("root")."/system/skins/".$skin."/templates/controls/".$namespaces[1].".html")){
            $res .= "/system/skins/".$skin."/templates/controls/".$namespaces[1].".html";
          }
          else{
            $res .= "/system/templates/controls/".$namespaces[1].".html";
          }
          $imported = true;
        }
        else if($namespaces[0] == "widget"){
          if(file_exists(Settings::getInstance()->get("root")."/system/skins/".$skin."/templates/widgets/".$namespaces[1].".html")){
            $res .= "/system/skins/".$skin."/templates/widgets/".$namespaces[1].".html";
          }
          else{
            $res .= "/system/templates/widgets/".$namespaces[1].".html";
          }
          $imported = true;
        }
      }
      if(!$imported){
        if(file_exists(Settings::getInstance()->get("root")."/system/skins/".$skin."/templates/".$name.".html")){
          $res .= "/system/skins/".$skin."/templates/".$name.".html";
        }
        else{
          $res .= "/system/templates/".$name.".html";
        }
      }
      return $res;
    }
  
    public function assign($type, $field, $value){
      $this->template = str_ireplace('{'.strtoupper($type).':'.$field.'}', $value, $this->template);
    }
  
    public function assign_var($field, $value){
      $this->template = str_ireplace('{VAR:'.$field.'}', $this->escape($value), $this->template);
    }
  
    public function add_loop_item($name){
      $res = 0;

      if(isset($this->loops[strtoupper($name)])){
        $this->loops[strtoupper($name)][] = $this->loop_templates[strtoupper($name)];
        $res = count($this->loops[strtoupper($name)]) - 1;
      }
   
      return $res;
    }
  
    public function assign_loop_var($loop_name, $index, $field, $value){
      if(isset($this->loops[strtoupper($loop_name)])){
        $this->loops[strtoupper($loop_name)][$index] = str_ireplace('{VAR:'.$field.'}', $value, $this->loops[strtoupper($loop_name)][$index]);
      }
    }
    
    public function show_if($name, $show = true){
      $this->ifs[strtoupper($name)] = $show;
      $this->ifs["!".strtoupper($name)] = !$show;
    }
  
    public function import($area, $template){
      if(file_exists($template)){
        $template = $this->read_file($template);
      }
      elseif(file_exists($this->template_path."/".$template)){
        $template = $this->read_file($template_path."/".$template);
      }
      $template = $this->initialize_loops($template);
      $this->template = str_ireplace('{INCLUDE:'.$area.'}', $template, $this->template);
    }
    
    private function replaceLanguageTokens(){
      preg_match_all("/{LANG:(.+)}/", $this->template, $matches, PREG_SET_ORDER);
      foreach($matches as $match){
        $translation = htmlentities($GLOBALS['language']->getString($match[1]));
        $this->template = str_ireplace($match[0],$translation,$this->template);
      }
    }
    
    private function replaceIcons(){
      preg_match_all("/{ICON:(.+)}/", $this->template, $matches, PREG_SET_ORDER);
      foreach($matches as $match){
        $translation = htmlentities(Icons::getIcon($match[1]));
        $this->template = str_ireplace($match[0],$translation,$this->template);
      }
    }
    
    private function replaceForms(){
      preg_match_all("/{FORM:(.+)}/", $this->template, $matches, PREG_SET_ORDER);
      foreach($matches as $match){
        $form = new Form($match[1]);
        $translation = $form->getCode();
        $this->template = str_ireplace($match[0],$translation,$this->template);
      }
    }
    
    private function removeHiddenIfBlocks($template){
      preg_match_all("/{IF:([!\w]+)[^}]*}((\s*?.*?)*){\/IF:\\1}/", $template, $matches, PREG_SET_ORDER);
      foreach ($matches as $match){
        if(!array_key_exists(strtoupper($match[1]), $this->ifs)){
          $template = str_ireplace($match[0], "", $template);
        }
        elseif(!$this->ifs[strtoupper($match[1])]){
          $template = str_ireplace($match[0], "", $template);
        }
        else{
          $template = str_ireplace($match[0], $match[2], $template);
        }
      }
      return $template;
    }

    private function unescape(){
      $this->template = str_ireplace("{TAG:","{",$this->template);
    }

    private function escape($var){
      return str_ireplace("{","{TAG:",$var);
    }
    
    public function getCode($escape = false){
      $this->template = $this->removeHiddenIfBlocks($this->template);
      foreach($this->loops as $key => $array){
        $loop_template = implode("\n",$array);
        $this->template = str_ireplace('<!--LOOP('.strtoupper($key).')-->', $loop_template, $this->template);
      }
      $this->replaceLanguageTokens();
      $this->replaceIcons();
      $this->replaceForms();
      if(!$escape){
        $this->unescape();
      }
      return $this->template;
    }
  
    public function output(){
      echo $this->getCode();
    }
  }
?>